<template>
  <div class="el-select tree-select deptTree">
    <el-row :gutter="20">
      <el-col :span="18">
        <!-- <el-alert
          v-if="userInfo.isAdmin != 0"
          title="说明：勾选部门目录根节点，代表默认选择所有部门；新建部门也会继承其关系"
          type="error"
          :closable="false"
        /> -->
        <el-tree
          v-if="userInfo.isAdmin == 1 || userInfo.isAdmin == 3"
          ref="tree"
          :data="treeOpt.data"
          :load="treeOpt.load"
          :lazy="treeOpt.lazy"
          :props="treeOpt.props"
          :node-key="treeOpt.key"
          :show-checkbox="treeOpt.showCheckbox"
          :check-strictly="true"
          :check-on-click-node="true"
          :expand-on-click-node="false"
          :default-expanded-keys="defaultExpandedKeys"
          :default-checked-keys="defaultCheckedNodes"
          class="tree-select-popover"
          @check="treeCheckhandle"
          @node-click="handleNodeClick"
          :class="className"
        >
          <template v-slot="{ node, data }">
            <div class="custom-tree-node">
              <div
                :title="node.label"
                :class="{ selected: node.selected, disabled: node.disabled }"
              >
                {{ node.label }}
              </div>
              <div v-if="!node.isLeaf || node.id == '0'">
                <el-button-group>
                  <el-button
                    type="primary"
                    size="mini"
                    @click.stop="selectAllChildren(node, data)"
                    >{{ $t("aicosCommon.all") }}</el-button
                  >
                  <el-button
                    type="primary"
                    size="mini"
                    @click.stop="cancelAllChildren(node, data)"
                    >{{ $t("aicosCommon.cancelBtn") }}</el-button
                  >
                </el-button-group>
              </div>
            </div>
          </template>
        </el-tree>
        <el-tree
          v-else
          ref="tree"
          :data="treeData"
          :props="treeProps"
          node-key="id"
          :show-checkbox="treeOpt.showCheckbox"
          :check-strictly="true"
          :check-on-click-node="true"
          :expand-on-click-node="false"
          :default-expanded-keys="defaultExpandedKeys"
          :default-checked-keys="defaultCheckedNodes"
          class="tree-select-popover"
          @check="treeCheckhandle"
          @node-click="handleNodeClick"
          :class="className"
        >
          <template v-slot="{ node, data }">
            <div class="custom-tree-node">
              <div
                :title="node.label"
                :class="{ selected: node.selected, disabled: node.disabled }"
              >
                {{ node.label }}
              </div>
              <div v-if="!node.isLeaf && !node.disabled">
                <el-button-group>
                  <el-button
                    type="primary"
                    size="mini"
                    @click.stop="selectAllChildren(node, data)"
                    >{{ $t("aicosCommon.all") }}</el-button
                  >
                  <el-button
                    type="primary"
                    size="mini"
                    @click.stop="cancelAllChildren(node, data)"
                    >{{ $t("aicosCommon.cancelBtn") }}</el-button
                  >
                </el-button-group>
              </div>
            </div>
          </template>
        </el-tree>
      </el-col>
      <el-col :span="6">
        <checkedList
          :checkedListData="selectData"
          :props="selectProps"
          @itemRemove="handleRemove"
          @itemRemoveAll="handleRemoveAll"
          :title="$t('system.dept.selectedDept')"
        />
      </el-col>
    </el-row>
  </div>
</template>
<script>
import { mapGetters } from "vuex";
import checkedList from "./checkedList";
import { isNull } from "@/util/qsgCommon.js";
import { getCanManagerDeptByAccount } from "@/api/system/dept";
export default {
  name: "TreeSelect",
  // directives: { Clickoutside },
  components: {
    checkedList,
  },
  inject: {
    elForm: {
      default: "",
    },

    elFormItem: {
      default: "",
    },
  },
  props: {
    className: {
      type: String,
      default: "",
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    // 当子节点都被选中时选中父节点，输入框中只显示父节点
    showCheckedStrategy: {
      type: String,
      default: "showParent",
    },
    showValue: {
      type: [String, Array],
      default: "",
    },
    value: {
      type: [String, Array],
      required: true,
    },
    placeholder: {
      type: String,
      default: "",
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    treeOption: {
      type: Object,
      default() {
        return {
          data: null,
          lazy: false,
          load: null,
          props: {
            children: "",
            label: "",
            disabled: "",
            isLeaf: "",
          },
          key: "",
          showCheckbox: true,
          checkStrictly: false,
          defaultExpandedKeys: [],
        };
      },
    },
  },
  data() {
    const me = this;
    const treeOpt = {
      showCheckbox: true,
      checkStrictly: false,
      ...this.treeOption,
    };
    if (treeOpt.lazy && treeOpt.load) {
      const load = treeOpt.load;
      treeOpt.load = function (node, resolve) {
        function newResolve(data) {
          resolve(data);
          setTimeout(me.nodeLoaded, 200);
        }
        load(node, newResolve);
      };
    }
    return {
      selectProps: {
        key: "id",
        label: "label",
      },
      showClose: false,
      popoverVisible: false,
      selectedLabel: "",
      inputWidth: 0,
      // selected: this.multiple ? [] : {},
      selectData: [],
      menuVisibleOnFocus: false,
      softFocus: false,
      allSelectedNodesLoaded: false,
      currentPlaceholder: "",
      initialInputHeight: 0,
      treeOpt,
      defaultCheckedNodes: [],
      defaultExpandedKeys: ["0"],
      //
      selectTreeData: [],
      treeProps: {
        children: "children",
        label: "name",
        disabled: "disabled",
        isLeaf: "",
      },
      treeData: [],
      managerDept: [],
    };
  },
  computed: {
    ...mapGetters(["userInfo", "managerDeptId"]),
    iconClass() {
      return this.popoverVisible ? "arrow-up is-reverse" : "arrow-up";
    },

    selectDisabled() {
      return this.disabled || (this.elForm || {}).disabled;
    },
  },
  watch: {
    popoverVisible(val) {
      if (!val) {
        this.menuVisibleOnFocus = false;
      }
    },
    value(val, oldVal) {
      let deSelect;
      if (this.multiple) {
        if (oldVal) {
          deSelect = oldVal.filter((item) => {
            return !val.includes(item);
          });
        }
      } else {
        deSelect = oldVal;
      }
      this.setSelected();
      this.setDeSelected(deSelect);
    },
  },
  mounted() {
    if (this.userInfo.isAdmin == 0) {
      this.managerDept = this.deepClone(this.managerDeptId);
      getCanManagerDeptByAccount().then((res) => {
        let data = res.data.data;
        this.treeData = [
          {
            name: this.$t("system.dept.dept"),
            id: "0",
            children: data,
            disabled: true,
          },
        ];
        this.traverseTree(this.treeData);
        this.setSelected(true);
      });
    } else {
      this.setSelected(true);
    }
    this.$nextTick(() => {
      this.defaultExpandedKeys = ["0", ...this.deepClone(this.value)];
      this.defaultCheckedNodes = this.deepClone(this.value);
    });
  },
  methods: {
    traverseTree(node) {
      if (node) {
        node.forEach((item) => {
          let flag = true;
          if (this.managerDept.includes(item.id)) {
            flag = false;
          }
          if (flag) {
            item.disabled = true;
          } else {
            item.disabled = false;
          }
          this.traverseTree(item.children);
        });
      }
    },
    treeCheckhandle(data, nodes) {
      this.selectTreeData = nodes.checkedNodes;
      this.handler(this.selectTreeData);
    },
    selectAllChildren(node, data) {
      if (node.data.id != "0") {
        node.setChecked(true);
        this.selectIn(data);
      }

      node.expand(() => {
        const children = node.childNodes;
        children.forEach((item) => {
          item.setChecked(true);
          this.selectIn(item.data);
          if (!item.isLeaf) {
            this.selectAllChildren(item, item.data);
          }
        });
      });
    },

    cancelAllChildren(node, data) {
      node.setChecked(false);
      this.selectOut(data);

      node.expand(() => {
        const children = node.childNodes;
        children.forEach((item) => {
          item.setChecked(false);
          this.selectOut(item.data);

          if (!item.isLeaf) {
            //console.log('自动打开子级并取消');
            this.cancelAllChildren(item, item.data);
          }
        });
      });
      //折叠子级
      node.collapse();
    },
    hasSelected(data) {
      return this.selectTreeData.some((item) => item.id === data.id);
    },
    selectIn(data) {
      if (!this.hasSelected(data)) {
        this.selectTreeData.push(data);
      }
      this.handler(this.selectTreeData);
    },
    selectOut(data) {
      this.selectTreeData = this.selectTreeData.filter((item) =>
        item.id == data.id ? "" : item
      );
      this.handler(this.selectTreeData);
    },
    handler(newVal) {
      this.value = [];
      const data = [];
      newVal.forEach((v) => {
        data.push({
          label: this.userInfo.isAdmin == 0 ? v.name : v.deptName,
          id: v.id,
          key: v.id,
        });
        this.value.push(v.id);
      });
      this.selectData = this.deepClone(data);
      this.$emit("input", this.value);
    },
    handleNodeClick(data, node, comp) {
      if (!node.isLeaf) {
        node.expand();
      }
    },
    handleSingleSelect(data, node) {
      // 已经选中
      if (node.selected) {
        return;
      }

      if (this.value) {
        const tree = this.$refs.tree;
        const oldNode = tree.getNode(this.value);
        if (oldNode) {
          oldNode.selected = false;
        }
      }

      this.selectedLabel = node.label;
      this.$emit("input", node.key);
    },
    handleMultipSelect(data, node) {
      const index = this.value.indexOf(node.key);

      if (index === -1) {
        this.value.push(node.key);
      } else {
        // 向node中注入selected
        this.$set(node, "selected", false);
        this.value.splice(index, 1);
        this.$emit("input", this.value);
      }
    },
    setSelected(flag = false) {
      // debugger
      const tree = this.$refs.tree;
      const showCheckbox = this.treeOpt.showCheckbox;
      if (this.multiple) {
        const result = [];
        let loaded = true;
        if (Array.isArray(this.value)) {
          if (showCheckbox) {
            tree.setCheckedKeys(this.value);
          }
          this.value.forEach((value, index) => {
            const node = tree.getNode(value);
            if (node) {
              this.$set(node, "selected", true);
              result.push(node);
            } else {
              result.push({
                label: this.showValue[index] || value,
                [this.treeOpt.key]: value,
                key: value,
              });
              loaded = false;
            }
          });
        }
        this.allSelectedNodesLoaded = loaded;
        this.selectData = result;
      } else {
        const node = tree.getNode(this.value);
        // lazy 加载的时候可能节点不存在
        if (node) {
          if (showCheckbox) {
            tree.setCheckedKeys([this.value]);
          }
          this.$set(node, "selected", true);
          this.selectData = node;
          // this.selectedLabel = node.label;
          this.allSelectedNodesLoaded = true;
        } else {
          // this.selectedLabel = this.showValue || this.value;
          this.selectData = [];
          this.allSelectedNodesLoaded = false;
          if (showCheckbox) {
            tree.setCheckedKeys([]);
          }
        }
      }
      if (flag) {
        this.selectTreeData = this.deepClone(this.selectData);
      }
    },
    handleRemove(item, index) {
      const node = this.$refs.tree.getNode(item);
      if (node) {
        node.setChecked(false);
      }
      this.value.splice(index, 1);
      this.selectData.splice(index, 1);
      this.$emit("input", this.value);
    },
    handleRemoveAll() {
      this.$refs.tree.setCheckedKeys([]);
      this.selectData = [];
      this.value = [];
      this.$emit("input", this.value);
    },
    setDeSelected(item) {
      const tree = this.$refs.tree;

      if (this.multiple) {
        if (Array.isArray(item)) {
          item.forEach((key) => {
            const node = tree.getNode(key);
            if (node) {
              this.$set(node, "selected", false);
            }
          });
        }
      } else {
        const node = tree.getNode(item);
        if (node) {
          this.$set(node, "selected", false);
        }
      }
    },
    nodeLoaded() {
      if (this.allSelectedNodesLoaded) {
        return;
      }
      this.setSelected();
    },
  },
};
</script>
<style lang="scss" scoped>
.deptTree {
  height: 431px;
  overflow-y: auto;
  border: 1px solid #dcdfe6;
  padding: 10px;
  .el-tree {
    height: 400px;
    overflow-y: auto;
    /deep/.el-tree-node {
      max-width: 100%;
    }
  }
}
.custom-tree-node {
  flex: 1;
  display: flex;
  width: 0;

  > div:first-child {
    flex: 1;
    font-size: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  > div:last-child {
    /deep/.el-button {
      padding: 4px 8px;
    }
  }

  /deep/.el-button-group {
    display: none;
  }

  &:hover {
    /deep/.el-button-group {
      display: block;
    }
  }
}
</style>
